E2e distributed tracing: suite-owned motel, browser OTLP, end-to-end trace join#979
Merged
Merged
Conversation
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ❌ Deployment failed View logs |
executor-marketing | 3b88f1b | Jun 12 2026, 05:46 PM |
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ❌ Deployment failed View logs |
executor-cloud | 3b88f1b | Jun 12 2026, 05:46 PM |
ad5a637 to
aa3e919
Compare
769da87 to
efa0fb3
Compare
9486dc2 to
0c1d824
Compare
5c2d4cc to
aab65e1
Compare
Our fork of kitlangton/motel (UsefulSoftwareCo/motel) with the query-
worker serialization fix: trace/span detail endpoints 500ed upstream
('Expected JSON value' — shared span objects tripping Schema.Unknown's
isJson guard). Run it with `bun run motel` in e2e/, then E2E_MOTEL=1
sends browser + server spans there during runs.
The browser surface harvests the W3C traceparent the web app already sends on each API request into the run's traces.json (id + offset + url). The runs viewer renders them as a Distributed traces table — one row per call, linking into the local motel's per-trace waterfall — so 'why was that page slow in this recording' goes from the recording to the exact click→server→DB trace in two clicks. Spans exist in motel when the run exported there (E2E_MOTEL=1); ids harvest regardless.
Every e2e run captures distributed traces. A suite-owned motel (local OTLP store) boots alongside the WorkOS/Autumn emulators — own port, runs-local store wiped per boot, torn down with the suite — and the cloud boot recipe gains an extraEnv seam so the globalsetup points the app's exporter at it (the same endpoint-agnostic layer that ships prod traces to Axiom). The web client exports OTLP spans when the build names an endpoint (VITE_PUBLIC_OTLP_TRACES_URL, proxied same-origin to motel in dev), and the cloud worker's http.server span adopts the caller's W3C traceparent — one trace id from the click in the browser through the worker to the database. Run pages list every harvested trace id with links into motel's waterfall. Also switches the worker's span processor Simple → Batch: per-span synchronous export fetches under the dev worker added enough request latency to flip the approval pause/resume race in e2e; batching removes the class, and the existing ctx.waitUntil(forceFlush) still drains per request in prod.
The web app's HttpClient sends a traceparent on its own, but mcporter's plain fetch does not — so the terminal half of a session was invisible in traces.json. The MCP surface now wraps the global fetch: every POST to the target's MCP endpoint gets a minted traceparent (the worker and DO already join whatever arrives) and lands in the ledger with the JSON-RPC method or tool name as its label, duration, status, and source: terminal. traces.json becomes a shared append-merge ledger (src/trace-harvest.ts) so the browser surface's harvested entries and the MCP surface's minted ones interleave by wall clock, and the trace rail tags each row with its window (⌨ terminal / ⊕ browser).
aab65e1 to
3b88f1b
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Every e2e run now captures distributed traces, hermetically.
runs/.motelwiped per boot, torn down with the suite). The cloud boot recipe gains anextraEnvseam so the globalsetup points the app's exporter at it — the same endpoint-agnostic layer that ships production traces to Axiom.packages/react): when the build names an endpoint (VITE_PUBLIC_OTLP_TRACES_URL), the web client exports spans and Effect's HttpClient sends a W3Ctraceparenton every API request. Same-origin in dev via a vite proxy to motel.apps/cloud/src/server.ts): the worker'shttp.serverspan adopts the caller's traceparent — one trace id from the click in the browser through the worker to the database.traces.jsonlabeled by JSON-RPC method/tool with duration + status.traces.jsonis a shared append-merge ledger (e2e/src/trace-harvest.ts) interleaving browser-harvested and terminal-minted entries.ctx.waitUntil(forceFlush)still drains per request in prod.Stack